package com.guaoran.study.future;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

import static com.guaoran.study.future.CompletableFutureDemo.sleep;
import static java.util.concurrent.TimeUnit.SECONDS;

/**
 * @Desc： CompletionService
 * @Auth gucheng
 * @Date 2020/10/31 下午2:29.
 */
public class CompletionServiceDemo {
    public static void main(String[] args) throws InterruptedException, ExecutionException {

        demo();
        forking();
    }

    public static void demo() throws InterruptedException, ExecutionException {

        // 创建线程池
        ExecutorService executor =
                Executors.newFixedThreadPool(3);
        // 创建CompletionService
        CompletionService<Integer> cs = new
                ExecutorCompletionService<>(executor);
        // 异步向电商S1询价
        cs.submit(() -> getPriceByS1());
        // 异步向电商S2询价
        cs.submit(() -> getPriceByS2());
        // 异步向电商S3询价
        cs.submit(() -> getPriceByS3());
        // 将询价结果异步保存到数据库
        for (int i = 0; i < 3; i++) {
            Integer r = cs.take().get();
            executor.execute(() -> save(r));
        }
    }

    public static Object forking() {

        // 创建线程池
        ExecutorService executor =
                Executors.newFixedThreadPool(3);
        // 创建CompletionService
        CompletionService<Integer> cs =
                new ExecutorCompletionService<>(executor);
        // 用于保存Future对象
        List<Future<Integer>> futures =
                new ArrayList<>(3);
        //提交异步任务，并保存future到futures
        futures.add(
                cs.submit(() -> geocoderByS1()));
        futures.add(
                cs.submit(() -> geocoderByS2()));
        futures.add(
                cs.submit(() -> geocoderByS3()));
        // 获取最快返回的任务执行结果
        Integer r = 0;
        try {
            // 只要有一个成功返回，则break
            for (int i = 0; i < 3; ++i) {
                r = cs.take().get();
                //简单地通过判空来检查是否成功返回
                if (r != null) {
                    break;
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            //取消所有任务
            for (Future<Integer> f : futures)
                f.cancel(true);
        }
        // 返回结果
        return r;
    }

    private static Integer geocoderByS3() {
        return getInteger();
    }

    private static Integer geocoderByS2() {
        return getInteger();
    }

    private static Integer geocoderByS1() {
        return getInteger();
    }

    private static Integer getInteger() {
        int i = new Random().nextInt(10);
        sleep(i + 1, SECONDS);
        return i;
    }

    private static void save(Integer r) {
        getInteger();
    }

    private static Integer getPriceByS3() {
        return getInteger();
    }

    private static Integer getPriceByS2() {
        return getInteger();
    }

    private static Integer getPriceByS1() {
        return getInteger();
    }
}
